// ****************************************************************
// Copyright 2012, Stephan Burguchev
// e-mail: me@sburg.net
// ****************************************************************
// *
using System;
using System.Collections.Generic;
using System.IO;
using NUnit.Framework;
using Updater.Common;
using Updater.Sources;

namespace Updater.Tests
{
    [TestFixture]
    public class WebSourceTests
    {
        [Test]
        public void Download_OneEmptyFile()
        {
            string testData = Config.TestDataDirectory;

            string dataEmpty = Path.Combine(testData, "empty.data").Replace('\\', '/');
            var dataEmptyUri = new Uri(Uri.UriSchemeFile + ":///" + dataEmpty);

            var src = new WebSource();
            src.AlwaysAcceptRemoteCertificate = true;
            using (var stream = new MemoryStream())
            {
                src.Download(
                    dataEmptyUri,
                    stream,
                    delegate(DownloadProgressInfo info)
                    {
                        Assert.LessOrEqual(info.DownloadedInBytes, info.FullSizeInBytes);
                        Assert.GreaterOrEqual(info.DownloadedInBytes, 0);
                        Assert.AreEqual(1024 * 1024, info.FullSizeInBytes);
                        Console.WriteLine(
                            "Downloading progress: {0} of {1} downloaded...",
                            info.DownloadedInBytes,
                            info.FullSizeInBytes);
                    });
                Assert.AreEqual(0, stream.Position);
            }
        }

        [Test]
        public void Download_OneLargeFile()
        {
            string testData = Config.TestDataDirectory;

            string data1Mb = Path.Combine(testData, "1mb.data").Replace('\\', '/');
            var data1MbUri = new Uri(Uri.UriSchemeFile + ":///" + data1Mb);

            var src = new WebSource();
            src.AlwaysAcceptRemoteCertificate = true;
            using (var stream = new MemoryStream())
            {
                src.Download(
                    data1MbUri,
                    stream,
                    delegate(DownloadProgressInfo info)
                    {
                        Assert.LessOrEqual(info.DownloadedInBytes, info.FullSizeInBytes);
                        Assert.GreaterOrEqual(info.DownloadedInBytes, 0);
                        Assert.AreEqual(1024 * 1024, info.FullSizeInBytes);
                        Console.WriteLine(
                            "Downloading progress: {0} of {1} downloaded...",
                            info.DownloadedInBytes,
                            info.FullSizeInBytes);
                    });
                stream.Seek(0, SeekOrigin.Begin);
                using (FileStream expected = File.OpenRead(data1Mb))
                {
                    FileAssert.AreEqual(expected, stream);
                }
            }
        }

        [Test]
        public void Download_OneSmallFile()
        {
            string testData = Config.TestDataDirectory;

            string data1Kb = Path.Combine(testData, "1kb.data").Replace('\\', '/');
            var data1KbUri = new Uri(Uri.UriSchemeFile + ":///" + data1Kb);

            var src = new WebSource();
            src.AlwaysAcceptRemoteCertificate = true;
            using (var stream = new MemoryStream())
            {
                int counter = 0;
                src.Download(
                    data1KbUri,
                    stream,
                    delegate(DownloadProgressInfo info)
                    {
                        ++counter;
                        Assert.LessOrEqual(info.DownloadedInBytes, info.FullSizeInBytes);
                        Assert.GreaterOrEqual(info.DownloadedInBytes, 0);
                        Assert.AreEqual(1024, info.FullSizeInBytes);
                        Console.WriteLine(
                            "Downloading progress: {0} of {1} downloaded...",
                            info.DownloadedInBytes,
                            info.FullSizeInBytes);
                    });
                Assert.AreEqual(1, counter);
                stream.Seek(0, SeekOrigin.Begin);
                using (FileStream expected = File.OpenRead(data1Kb))
                {
                    FileAssert.AreEqual(expected, stream);
                }
            }
        }

        [Test]
        public void Download_SeveralFiles()
        {
            string testData = Config.TestDataDirectory;

            string data1Kb = Path.Combine(testData, "1kb.data").Replace('\\', '/');
            var data1KbUri = new Uri(Uri.UriSchemeFile + ":///" + data1Kb);
            string data512Kb = Path.Combine(testData, "512kb.data").Replace('\\', '/');
            var data512KbUri = new Uri(Uri.UriSchemeFile + ":///" + data512Kb);
            string data1Mb = Path.Combine(testData, "1mb.data").Replace('\\', '/');
            var data1MbUri = new Uri(Uri.UriSchemeFile + ":///" + data1Mb);

            const int totalSize = 1537 * 1024;
            var src = new WebSource();
            src.AlwaysAcceptRemoteCertificate = true;
            using (var stream1Kb = new MemoryStream())
            {
                using (var stream512Kb = new MemoryStream())
                {
                    using (var stream1Mb = new MemoryStream())
                    {
                        long lastDownloadedInBytes = -1;
                        src.Download(
                            new Dictionary<Uri, Stream>
                                {
                                    { data1KbUri, stream1Kb },
                                    { data512KbUri, stream512Kb },
                                    { data1MbUri, stream1Mb },
                                },
                            delegate(DownloadProgressInfo info)
                            {
                                Assert.LessOrEqual(info.DownloadedInBytes, info.FullSizeInBytes);
                                Assert.GreaterOrEqual(info.DownloadedInBytes, 0);
                                Assert.LessOrEqual(info.FullSizeInBytes, totalSize);
                                Console.WriteLine(
                                    "Downloading progress: {0} of {1} downloaded...",
                                    info.DownloadedInBytes,
                                    info.FullSizeInBytes);
                                lastDownloadedInBytes = info.DownloadedInBytes;
                            });
                        Assert.AreEqual(totalSize, lastDownloadedInBytes);
                        stream1Kb.Seek(0, SeekOrigin.Begin);
                        using (FileStream expected = File.OpenRead(data1Kb))
                        {
                            FileAssert.AreEqual(expected, stream1Kb);
                        }

                        stream512Kb.Seek(0, SeekOrigin.Begin);
                        using (FileStream expected = File.OpenRead(data512Kb))
                        {
                            FileAssert.AreEqual(expected, stream512Kb);
                        }

                        stream1Mb.Seek(0, SeekOrigin.Begin);
                        using (FileStream expected = File.OpenRead(data1Mb))
                        {
                            FileAssert.AreEqual(expected, stream1Mb);
                        }
                    }
                }
            }
        }
    }
}
